/**
    ******************************************************************************
    * @file    main.c 
    * @author  18408107475@163.com
    * @version v1.0
    * @date    2025/03/22
    * @brief   主程序文件，实现以下功能：
    *           - 使用PE4引脚检测按键下降沿触发外部中断
    *           - 中断触发时控制PB5和PE5引脚LED状态翻转
    *           - 初始化蜂鸣器控制引脚PB8
    *           硬件连接：
    *           - 按键连接PE4，按下时接地（下降沿触发）
    *           - PB5和PE5接共阴极LED（低电平点亮）
    *           - PB8接蜂鸣器驱动电路（高电平触发）
    ******************************************************************************
**/

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f10x.h"  // STM32标准外设库头文件，包含寄存器定义和库函数声明

/* 函数声明 ------------------------------------------------------------------*/
void LED_STD_Config(void);     // LED初始化函数
void KEY_STD_Config(void);     // 按键中断配置函数
void BEEP_STD_Config(void);    // 蜂鸣器初始化函数

/* 全局变量 ------------------------------------------------------------------*/
// 无全局变量

/**
    ******************************************************************************
    * 函数名称：EXTI4_IRQHandler
    * 功能描述：EXTI4中断服务函数，处理PE4引脚的中断事件
    * 输入参数：无
    * 返回值  ：无
    * 注意事项：
    *   - 检测到PE4下降沿时，关闭PB5 LED，点亮PE5 LED
    *   - 必须清除中断挂起位防止重复进入中断
    ******************************************************************************
**/
void EXTI4_IRQHandler(void)
{
    /* 检查EXTI4线路是否触发中断 */
    if(EXTI_GetITStatus(EXTI_Line4) != RESET)
    {
        /* 控制LED状态 */
        GPIO_ResetBits(GPIOB, GPIO_Pin_5);  // PB5输出低电平（LED亮）
        GPIO_SetBits(GPIOE, GPIO_Pin_5);    // PE5输出高电平（LED灭）
        
        /* 清除EXTI4中断挂起标志 */
        EXTI_ClearITPendingBit(EXTI_Line4); 
    }
}

/**
    ******************************************************************************
    * 函数名称：LED_STD_Config
    * 功能描述：初始化PB5和PE5引脚为推挽输出模式，配置LED初始状态
    * 输入参数：无
    * 返回值  ：无
    * 配置流程：
    *   1. 开启GPIOB/GPIOE时钟
    *   2. 配置PB5和PE5为50MHz推挽输出
    *   3. 设置PB5高电平（LED灭）、PE5低电平（LED亮）
    ******************************************************************************
**/
void LED_STD_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;  // GPIO配置结构体

    /* 开启GPIOB和GPIOE时钟（APB2总线） */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);

    /* 配置PB5引脚 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;        // 选择引脚5
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  // 高速模式
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);             // 应用配置到GPIOB

    /* 配置PE5引脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;         // 选择引脚5
    GPIO_Init(GPIOE, &GPIO_InitStructure);             // 应用配置到GPIOE

    /* 设置初始状态 */
    GPIO_SetBits(GPIOB, GPIO_Pin_5);   // PB5高电平（LED灭）
    GPIO_ResetBits(GPIOE, GPIO_Pin_5); // PE5低电平（LED亮）
}

/**
    ******************************************************************************
    * 函数名称：BEEP_STD_Config
    * 功能描述：初始化PB8引脚为蜂鸣器控制引脚
    * 输入参数：无
    * 返回值  ：无
    * 配置流程：
    *   1. 开启GPIOB时钟
    *   2. 配置PB8为50MHz推挽输出
    *   3. 初始状态低电平（蜂鸣器关闭）
    ******************************************************************************
**/
void BEEP_STD_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /* 开启GPIOB时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    /* 配置PB8引脚 */
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_8;          // 蜂鸣器控制引脚
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;    // 推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;     // 高速模式
    GPIO_Init(GPIOB, &GPIO_InitStruct);               // 应用配置

    /* 初始状态：蜂鸣器关闭 */
    GPIO_ResetBits(GPIOB, GPIO_Pin_8);  // 低电平不触发蜂鸣器
}

/**
    ******************************************************************************
    * 函数名称：KEY_STD_Config
    * 功能描述：配置PE4引脚为按键输入，设置外部中断和NVIC
    * 输入参数：无
    * 返回值  ：无
    * 配置流程：
    *   1. 开启GPIOE时钟
    *   2. 配置PE4为浮空输入模式
    *   3. 开启AFIO时钟（重映射功能）
    *   4. 将PE4映射到EXTI4中断线
    *   5. 配置EXTI4为下降沿触发
    *   6. 设置NVIC优先级并启用中断
    ******************************************************************************
**/
void KEY_STD_Config(void)
{
    EXTI_InitTypeDef   EXTI_InitStructure;
    GPIO_InitTypeDef   GPIO_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;

    /* 开启GPIOE时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

    /* 配置PE4为浮空输入（依赖外部电路上拉） */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入模式
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    /* 开启AFIO时钟（EXTI配置需要） */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    /* 将PE4映射到EXTI4中断线 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);

    /* 配置EXTI4参数 */
    EXTI_InitStructure.EXTI_Line = EXTI_Line4;           // 中断线4
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  // 中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;            // 使能中断线
    EXTI_Init(&EXTI_InitStructure);

    /* 配置NVIC */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;     // 中断通道EXTI4
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; // 抢占优先级15（最低）
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;        // 子优先级15
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;      // 启用中断通道
    NVIC_Init(&NVIC_InitStructure);
}

/**
    ******************************************************************************
    * 函数名称：main
    * 功能描述：主函数，初始化外设后进入待机循环
    * 输入参数：无
    * 返回值  ：int类型（实际不会返回）
    * 执行流程：
    *   1. 初始化LED、按键中断、蜂鸣器
    *   2. 进入无限循环，等待中断触发
    ******************************************************************************
**/
int main(void)
{
    /* 外设初始化 */
    LED_STD_Config();    // 初始化LED引脚
    KEY_STD_Config();    // 配置按键中断
    BEEP_STD_Config();   // 初始化蜂鸣器

    /* 主循环 */
    while(1)
    {
        /* 此处可添加其他后台任务 */
    }
}

/*************************************END OF FILE**************************************/